package p.ithorns.tools.translator.apt.creator;

import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer;
import com.sun.tools.javac.util.Name;
import p.ithorns.tools.translator.apt.AbstractHandler;
import p.ithorns.tools.translator.apt.utils.AptUtil;
import p.ithorns.tools.translator.apt.BaseProcessor;
import p.ithorns.tools.translator.apt.model.AnnotateMeta;
import p.ithorns.tools.translator.apt.model.AnnotatedParam;
import p.ithorns.tools.translator.apt.model.FieldMeta;

import javax.lang.model.element.Element;
import javax.lang.model.element.VariableElement;

/**
 * FieldCreator
 *
 * @author HtL
 * @date 2025/4/11 16:41
 * @since 1.0.0
 */
public class FieldCreator extends BaseCreator {

    public FieldCreator(BaseProcessor owner) {
        super(owner);
    }

    public JCTree.JCVariableDecl create(JCTree.JCClassDecl jcClass, JCTree.JCVariableDecl source) {
        String fieldFqn = AptUtil.makeJCVarDeclFQN(jcClass, source);

        FieldMeta fieldMeta = AptUtil.buildFieldMeta(source);

        processor.info("[FieldCreator]-> create [{}] begin!", fieldFqn);

        // 创建新字段
        String fieldName = fieldMeta.getLabel();
        try {
            List<JCTree.JCAnnotation> newAnnotations = fieldMeta.newAnnotations(this::makeAnnotation);
            JCTree.JCVariableDecl target = createNewField(fieldName, newAnnotations);
            // 访问修饰符
            target.mods.flags = source.mods.flags;
            // 替换成新的注解
            processor.info("[FieldCreator]-> Class add new field: ↲\r\n{}", target.toString());
            return target;
        } catch (Exception e) {
            processor.error("[FieldCreator]-> create [{}] failed: {}.", fieldFqn, e.getMessage());
            return null;
        }
    }

    public JCTree.JCVariableDecl create(Element element) {
        VariableElement varElement = (VariableElement) element;
        List<JCTree.JCAnnotation> fieldAnnotations = processor.getAnnotations(element);
        FieldMeta fieldMeta = new FieldMeta(varElement, META_NAME, fieldAnnotations);

        String fieldFqn = AptUtil.makeVarElementFQN(element);

        processor.info("[FieldCreator]-> create [{}] begin!", fieldFqn);

        // 创建新字段
        String fieldName = fieldMeta.getLabel();
        try {
            List<JCTree.JCAnnotation> newAnnotations = fieldMeta.newAnnotations(this::makeAnnotation);
            return createNewField(fieldName, newAnnotations);
        } catch (Exception e) {
            processor.error("[FieldCreator]-> create [{}] failed: {}.", fieldFqn, e.getMessage());
            return null;
        }
    }

    private JCTree.JCVariableDecl createNewField(String fieldName, List<JCTree.JCAnnotation> annotations) {
        // 复制原有字段信息
        JCTree.JCExpression type = treeMaker.Ident(names.fromString("String"));

        // 新字段名
        Name newName = names.fromString(fieldName);
        // 创建新字段
        JCTree.JCModifiers modifiers = treeMaker.Modifiers(Flags.PRIVATE, annotations);

        // 将新字段添加到类声明中
        return treeMaker.VarDef(modifiers, newName, type, null);
    }

    private JCTree.JCAnnotation makeAnnotation(AnnotateMeta meta) {
        String name = meta.getFqn();
        AbstractHandler handler = AbstractHandler.get(name);
        if (null == handler) {
            processor.warn("[FieldCreator]-> There's no handler for type: @{}", name);
            return null;
        }

        // 处理MapField
        AnnotateMeta newMeta = handler.handle(meta);
        ListBuffer<JCTree.JCExpression> args = new ListBuffer<>();
        for (AnnotatedParam param : newMeta.getParams()) {
            String key = param.getName();
            Object value = param.getValue();
            JCTree.JCAssign assign = (JCTree.JCAssign) processor.makeArg(key, value);
            args.append(assign);
        }

        // 获取注解FQN
        return processor.makeAnnotation(newMeta.getFqn(), args.toList());
    }

}